import cloud from "@lafjs/cloud";
const db = cloud.database();
import {
  resultOk,
  hashPassword,
  checkPermission,
  resultFail,
  isEmptyObject
} from "@/utils";
const permissionName = "admin:staff";
const adminDbName = "admin-staff";
const roleDbName = "role";
const _ = db.command; // 这里拿到指令
interface Action {
  [key: string]: {
    method: string[];
    auth: boolean;
    permissions?: boolean;
    handler: Function;
  };
}

const actions: Action = {};
// 创建
actions.create = {
  method: ["POST"],
  auth: true,
  permissions: true,
  async handler(ctx: FunctionContext) {
    // check params
    const { username, password, nickName, sex, status, deptId, roleList } =
      ctx.body;
    if (!username || !password) {
      return resultFail("账号密码不能为空");
    }

    // check exist
    const { total } = await db
      .collection(adminDbName)
      .where({ username })
      .count();
    if (total > 0) {
      return resultFail("账号已存在");
    }

    // check role validation
    const { total: valid_count } = await db
      .collection(roleDbName)
      .where({
        _id: db.command.in(roleList)
      })
      .count();
    if (valid_count !== roleList.length) {
      return resultFail("无此角色");
    }

    // add admin
    const r = await db.collection(adminDbName).add({
      username,
      nickName,
      deptId: deptId,
      roleList: roleList ?? [],
      created_at: Date.now(),
      updated_at: Date.now(),
      status,
      sex
    });

    await db.collection("password").add({
      uid: r.id,
      password: hashPassword(password),
      type: "login",
      status: "active",
      created_at: Date.now(),
      updated_at: Date.now()
    });
    return resultOk(r);
  }
};
actions.modifyPassword = {
  method: ["POST"],
  auth: true,
  permissions: false,
  async handler(ctx: FunctionContext) {
    // check params
    const { password } = ctx.body;
    if (!password) {
      return resultFail("密码不能为空");
    }
    const { data: admin } = await db
      .collection(adminDbName)
      .where({ _id: ctx.user._id })
      .withOne({
        query: db.collection("password").where({ type: "login" }),
        localField: "_id",
        foreignField: "uid",
        as: "password"
      })
      .getOne();
    const isMatchPassword = admin.password?.password === hashPassword(password);
    if (isMatchPassword) return resultFail("新密码和现有密码一致");
    const r = await db
      .collection(adminDbName)
      .where({ _id: admin.password._id })
      .update({
        updated_at: Date.now(),
        password: hashPassword(password)
      });
    return resultOk(r);
  }
};
// 列表
actions.list = {
  method: ["POST"],
  auth: true,
  permissions: true,
  async handler(ctx: FunctionContext) {
    const {
      currentPage = 1,
      deptId = "0",
      pageSize = 20,
      name,
      status
    } = ctx.body;
    // 数据库操作
    const db = cloud.database();
    const { total } = await db.collection(adminDbName).count();
    const where: { name?: any; deptId?: String; status?: Boolean } = {};

    if (name) {
      const nameQuery = `/${name}/`;
      where.name = { $regex: nameQuery };
    }
    if (status) {
      where.status = status === 0;
    }
    if (deptId !== "0") {
      where.deptId = deptId;
    }
    const skip = currentPage === 0 ? 0 : currentPage - 1;
    let dbSelect = db
      .collection(adminDbName)
      .skip(skip * pageSize)
      .limit(pageSize);
    if (!isEmptyObject(where)) {
      dbSelect = dbSelect.where(where);
    }
    const r = await dbSelect.get();
    return resultOk({
      result: r.data.map(res => {
        res.id = res._id;
        return res;
      }),
      total,
      currentPage,
      pageSize,
      pageCount: Math.ceil(total / pageSize)
    });
  }
};
// 删除
actions.delete = {
  method: ["POST"],
  auth: true,
  permissions: true,
  async handler(ctx: FunctionContext) {
    // check params
    const { _id } = ctx.body;
    if (!_id) {
      return resultFail("id不能为空");
    }

    // check id
    const { data: admin } = await db
      .collection(adminDbName)
      .where({ _id: ctx.user._id })
      .withOne({
        query: db.collection("password").where({ type: "login" }),
        localField: "_id",
        foreignField: "uid",
        as: "password"
      })
      .getOne();
    if (!admin) {
      return resultFail("无此数据");
    }
    await db.collection("password").doc(admin.password._id).remove();
    const r = await db.collection(adminDbName).doc(_id).remove();
    return resultOk(r);
  }
};
// 获取单个信息
actions.info = {
  method: ["POST"],
  auth: true,
  permissions: true,
  async handler(ctx: FunctionContext) {
    const { data: result } = await db
      .collection(adminDbName)
      .where({ _id: ctx.body.id })
      .getOne();
    return resultOk({
      ...result
    });
  }
};
// 更新
actions.update = {
  method: ["POST"],
  auth: true,
  permissions: true,
  async handler(ctx: FunctionContext) {
    const body = ctx.body;
    if (!body.id) {
      return resultFail("数据不完整,请检查数据");
    }
    const items = Object.assign({}, body);
    const { total: PermsTotal } = await db
      .collection(adminDbName)
      .where({
        username: items.username,
        _id: _.neq(body.id)
      })
      .count();
    if (PermsTotal > 0) {
      return resultFail("用户已存在");
    }
    delete items._id;
    delete items.id;
    const r = await db
      .collection(adminDbName)
      .where({ _id: body.id })
      .update({
        ...items,
        updated_at: new Date().getTime()
      });
    return resultOk(r);
  }
};

// 入口，拦截器
export default async function (ctx: FunctionContext) {
  const { action } = ctx.query;

  // 黑名单处理和访问频率处理，此处省去。见帖子：https://forum.laf.run/d/130/7
  // 顺便说一下，黑名单的处理可以放在`__interceptor__`中，这里仅处理频率问题即可。

  // 没有 action 或没找到 action 报错
  if (!action || !actions[action]) {
    return resultFail("请求失败");
  }

  const { method, auth, handler, permissions } = actions[action];

  // method 不符
  if (!method.includes(ctx.method)) {
    return resultFail("请求失败");
  }

  // 鉴权
  if (auth && ctx.user === null) {
    return resultFail("用户未登陆", -2);
  }

  if (
    permissions &&
    !checkPermission(ctx.user, `${permissionName}:${action}`)
  ) {
    return resultFail("未授权访问");
  }

  // 执行
  if (handler) {
    return await handler(ctx);
  }
  // 能执行到这里肯定哪儿写错了
  return resultFail("请求失败");
}
